package com.asggo.g21.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import io.lettuce.core.ClientOptions;
import io.lettuce.core.protocol.ProtocolVersion;
import lombok.extern.slf4j.Slf4j;
import org.redisson.client.codec.StringCodec;
import org.redisson.codec.CompositeCodec;
import org.redisson.codec.TypedJsonJacksonCodec;
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by IntelliJ IDEA.
 *
 * @author eric 2023/12/15 17:41
 */
@Configuration
@Slf4j
public class RedisConfiguration {

  @Bean
  public RedissonAutoConfigurationCustomizer redissonCustomizer(
      ObjectMapper objectMapper
  ) {
    return config -> {
      ObjectMapper om = objectMapper.copy();
      om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
      // 指定序列化输入的类型，类必须是非final修饰的。序列化时将对象全类名一起保存下来
      om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
          ObjectMapper.DefaultTyping.NON_FINAL);
      TypedJsonJacksonCodec jsonCodec = new TypedJsonJacksonCodec(Object.class, om);
      // 组合序列化 key 使用 String 内容使用通用 json 格式
      CompositeCodec codec = new CompositeCodec(StringCodec.INSTANCE, jsonCodec, jsonCodec);
      config.setCodec(codec);

      config.useSingleServer()
              .setConnectionMinimumIdleSize(1);

      log.info("初始化 redisson 配置");
    };
  }

  /**
   * fix
   * <a href="https://github.com/lettuce-io/lettuce-core/issues/1201">...</a>
   * <a href="https://github.com/lettuce-io/lettuce-core/issues/1543">...</a>
   */
  @Bean
  public LettuceClientConfigurationBuilderCustomizer redisBuilderCustomizer() {
    return builder -> builder.clientOptions(
        ClientOptions
            .builder()
            .protocolVersion(ProtocolVersion.RESP3)
            .build()
    );
  }
}
